package edu.cornell.cs4740.qa;

import java.io.File;
import java.util.HashSet;
import java.util.List;

import edu.cornell.cs4740.qa.parsing.TokenFactory;
import edu.cornell.cs4740.qa.pos.PosTagger;
import edu.cornell.cs4740.qa.utilities.Util;

public class Question {
	public static enum Type {
		WHO, WHERE, WHEN, WHAT, HOW_MUCH, HOW_TO, OTHER
	}

	private static HashSet<String> stopHash = null;

	private String questionNum;
	private String questionText;
	private Sentence questionSentence;
	private Type type = Type.OTHER;

	public Question(String questionNum, String text) {
		this.questionNum = questionNum;
		this.questionText = text;
		tokenizeQuestion();
		classifyQuestion();
	}

	private void tokenizeQuestion() {
		TokenFactory tokenFactory = new TokenFactory();
		List<WordContainer> tokenList = tokenFactory
				.sentenceToTokens(questionText);
		PosTagger posTagger = new PosTagger(new File("models/pos-en-general-brown.HiddenMarkovModel"));
		posTagger.tagTokens(tokenList);
		questionSentence = new Sentence(tokenList);
	}

	public String getQuestionNumber() {
		return questionNum;
	}

	public String getQuestionText() {
		return questionText;
	}

	public Type getQuestionType() {
		return type;
	}

	public Sentence getQuestionSentence() {
		return questionSentence;
	}

	public Sentence getQuestionSentenceWithoutPunc() {
		return questionSentence; // TODO
	}

	public void setQuestionType(Type type) {
		this.type = type;
	}

	public void classifyQuestion() {
		List<WordContainer> stringSentence = questionSentence.getAllWords();
		// First classify what type of question just based on first word.
		String s = stringSentence.get(0).getWord();
		if (s.indexOf("who") >= 0)
			this.type = Type.WHO;
		else if (s.indexOf("what") >= 0)
			this.type = Type.WHAT;
		else if (s.indexOf("where") >= 0)
			this.type = Type.WHERE;
		else if (s.indexOf("when") >= 0)
			this.type = Type.WHEN;
		else if (s.indexOf("how") >= 0)
			this.type = Type.HOW_TO;
		
		if(questionNum.equals(Util.walkThrough)){
			System.out.println("First type is labeled as type.WHERE because \"where\" was found in question text");
		}

		// Nothing more to do if it is of these types.
		if (this.type == Type.WHO || this.type == Type.WHERE
				|| this.type == Type.WHEN) {
			if(questionNum.equals(Util.walkThrough)){
				System.out.println("Because it is of type who, where, or when, question classification ends");
			}
			return;
		}

		// We check the next word to see if it is a "quantity" how question.
		else if (this.type == Type.HOW_TO) {
			s = stringSentence.get(1).getPos();
			s = s.toLowerCase();
			if (s.equals("jj") || s.equals("jj$") || s.equals("jjr")
					|| s.equals("jjs") || s.equals("jjt")
					|| s.equals("rb") || s.equals("rb$") || s.equals("rbr")
					|| s.equals("rbt") || s.equals("rn") || s.equals("ap")
					|| s.equals("ap$"))
				this.type = Type.HOW_MUCH;
			return;
		}

		else if (this.type == Type.WHAT) {
			for (int i = 1; i < stringSentence.size(); i++) {
				s = stringSentence.get(i).getWord();
				s = s.toLowerCase();
				// Make more sophisticated, if time allows.
				// Right now, did not want to make too aggressive, as per advice
				// of the professor.
				if (s.equals("location")) {
					this.type = Type.WHERE;
					return;
				}
				if (s.equals("date")) {
					this.type = Type.WHEN;
					return;
				}
				if (s.equals("name")) {
					this.type = Type.WHO;
					return;
				}
			}
			return;
		}

		return;
	}

	public void buildStopHash() {
		String[] stopList = { "a", "about", "above", "above", "across",
				"after", "afterwards", "again", "against", "all", "almost",
				"alone", "along", "already", "also", "although", "always",
				"am", "among", "amongst", "amoungst", "amount", "an", "and",
				"another", "any", "anyhow", "anyone", "anything", "anyway",
				"anywhere", "are", "around", "as", "at", "back", "be",
				"became", "because", "become", "becomes", "becoming", "been",
				"before", "beforehand", "behind", "being", "below", "beside",
				"besides", "between", "beyond", "bill", "both", "bottom",
				"but", "by", "call", "can", "cannot", "cant", "co", "con",
				"could", "couldnt", "cry", "de", "describe", "detail", "do",
				"done", "down", "due", "during", "each", "eg", "eight",
				"either", "eleven", "else", "elsewhere", "empty", "enough",
				"etc", "even", "ever", "every", "everyone", "everything",
				"everywhere", "except", "few", "fifteen", "fify", "fill",
				"find", "fire", "first", "five", "for", "former", "formerly",
				"forty", "found", "four", "from", "front", "full", "further",
				"get", "give", "go", "had", "has", "hasnt", "have", "he",
				"hence", "her", "here", "hereafter", "hereby", "herein",
				"hereupon", "hers", "herself", "him", "himself", "his", "how",
				"however", "hundred", "ie", "if", "in", "inc", "indeed",
				"interest", "into", "is", "it", "its", "itself", "keep",
				"last", "latter", "latterly", "least", "less", "ltd", "made",
				"many", "may", "me", "meanwhile", "might", "mill", "mine",
				"more", "moreover", "most", "mostly", "move", "much", "must",
				"my", "myself", "name", "namely", "neither", "never",
				"nevertheless", "next", "nine", "no", "nobody", "none",
				"noone", "nor", "not", "nothing", "now", "nowhere", "of",
				"off", "often", "on", "once", "one", "only", "onto", "or",
				"other", "others", "otherwise", "our", "ours", "ourselves",
				"out", "over", "own", "part", "per", "perhaps", "please",
				"put", "rather", "re", "same", "see", "seem", "seemed",
				"seeming", "seems", "serious", "several", "she", "should",
				"show", "side", "since", "sincere", "six", "sixty", "so",
				"some", "somehow", "someone", "something", "sometime",
				"sometimes", "somewhere", "still", "such", "system", "take",
				"ten", "than", "that", "the", "their", "them", "themselves",
				"then", "thence", "there", "thereafter", "thereby",
				"therefore", "therein", "thereupon", "these", "they", "thickv",
				"thin", "third", "this", "those", "though", "three", "through",
				"throughout", "thru", "thus", "to", "together", "too", "top",
				"toward", "towards", "twelve", "twenty", "two", "un", "under",
				"until", "up", "upon", "us", "very", "via", "was", "we",
				"well", "were", "what", "whatever", "when", "whence",
				"whenever", "where", "whereafter", "whereas", "whereby",
				"wherein", "whereupon", "wherever", "whether", "which",
				"while", "whither", "who", "whoever", "whole", "whom", "whose",
				"why", "will", "with", "within", "without", "would", "yet",
				"you", "your", "yours", "yourself", "yourselves", "the" };
		HashSet<String> stopHash = new HashSet<String>();
		for (int i = 0; i < stopList.length; i++) {
			stopHash.add(stopList[i]);
		}
		this.stopHash = stopHash;
	}

	// removes all words that aren't informational about a question
	// to be used for the baseline
	public Sentence questionWithoutIrrelevantWords() {
		if (stopHash == null) {
			buildStopHash();
		}
		List<WordContainer> stringSentence = questionSentence.getAllWords();
		Sentence newQuestionSentence = new Sentence();
		for (int i = 0; i < stringSentence.size(); i++) {
			if (!stopHash.contains(stringSentence.get(i).getWord())) {
				newQuestionSentence.addWord(stringSentence.get(i));
			}
		}
		return newQuestionSentence;
	}
}
